<template>
  <div class="app-preview">
    <div v-if="appInfo" class="app-info">
      <el-row :gutter="15" class="app-meta">
        <el-col :span="6">
          <div class="app-icon-col">
            <img :src="iconBase64" class="app-icon" alt="APP 图标" />
          </div>
        </el-col>
        <el-col :span="18">
          <el-row
            style="color: var(--MainText); font-size: 25px; font-weight: bold"
          >
            <img
              v-if="getPlatform() === 'iOS'"
              class="platform-icon"
              src="@/assets/icon_platform_ios.svg"
              :alt="getPlatform()"
            />
            <img
              v-else-if="getPlatform() === 'Android'"
              class="platform-icon"
              src="@/assets/icon_platform_android.svg"
              :alt="getPlatform()"
            />
            <img
              v-else
              class="platform-icon"
              src="@/assets/icon_platform_unknown.svg"
              :alt="getPlatform()"
            />
            {{ appInfo.Name }}
          </el-row>
          <el-row :gutter="15" v-if="appInfo.Platform == 'iOS'">
            <el-col class="app-meta-property" :span="8">
              bundle id
            </el-col>
            <el-col :span="16">
              {{ appInfo.PackageName }}
            </el-col>
          </el-row>
          <el-row :gutter="15" v-if="appInfo.Platform == 'Android'">
            <el-col class="app-meta-property" :span="8"> package name </el-col>
            <el-col :span="16">
              {{ appInfo.PackageName }}
            </el-col>
          </el-row>

          <el-row :gutter="15" v-if="appInfo.Platform == 'iOS'">
            <el-col class="app-meta-property" :span="8"> version </el-col>
            <el-col :span="16">{{ appInfo.Version }}</el-col>
            <el-col class="app-meta-property" :span="8"> build </el-col>
            <el-col :span="16">{{ appInfo.BuildVersion }}</el-col>
          </el-row>
          <el-row :gutter="15" v-if="appInfo.Platform == 'Android'">
            <el-col class="app-meta-property" :span="8"> version name </el-col>
            <el-col :span="16">
              {{ appInfo.Version }}
            </el-col>
            <el-col class="app-meta-property" :span="8"> version code </el-col>
            <el-col :span="16">
              {{ appInfo.BuildVersion }}
            </el-col>
          </el-row>
          <el-row :gutter="15">
            <el-col class="app-meta-property" :span="8"> File MD5 </el-col>
            <el-col :span="16">
              {{ fileMd5 }}
            </el-col>
          </el-row>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="20" :offset="2">
          <el-form :model="appInfo" label-position="top">
            <el-form-item label="标题">
              <el-input
                v-model="appInfo.VersionTitle"
                show-word-limit
                maxlength="100"
              ></el-input>
            </el-form-item>
            <el-form-item label="更新日志">
              <el-input
                v-model="appInfo.UpdateLog"
                type="textarea"
                show-word-limit
                maxlength="5000"
                :autosize="{ minRows: 5, maxRows: 10 }"
              ></el-input>
            </el-form-item>
          </el-form>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="9">
          <el-button @click="submit" type="primary">上传</el-button>
          <el-button @click="cancel">取消</el-button>
        </el-col>
      </el-row>
    </div>
    <div v-else class="placeholder"></div>
    <transition name="fade">
      <div class="app-loading" v-if="loading != null">
        <div v-loading="loading != null"></div>
        {{ loading }}
      </div>
    </transition>
  </div>
</template>

<script>
import CryptoJS from 'crypto-js'
import { Base64 } from 'js-base64'
import { ElMessage } from 'element-plus'
import AppInfoParser from 'app-info-parser'

export default {
  components: {},
  props: {
    // 文件对象
    file: {
      type: Object,
      default () {
        return {
          name: ''
        }
      }
    }
  },
  data () {
    return {
      loading: '加载中。。。',
      appInfo: null,
      fileMd5: null,
      iconFile: null,
      iconBase64: null,
      iconMd5: null
    }
  },
  computed: {
  },
  watch: {
    file () {
      this.appInfo = null
      this.loadAppInfo()
    }
  },

  methods: {
    /// 加载appInfo
    async loadAppInfo () {
      this.loading = '读取APP信息。。。'
      // 从文件加载
      if (!this.file) {
        console.log('没有文件')
        return
      }
      const appInfo = {}
      appInfo.Platform = this.getPlatform()
      const infoParser = new AppInfoParser(this.file)
      try {
        const info = await infoParser.parse()
        if (appInfo.Platform === 'iOS') {
          appInfo.Name = info.CFBundleDisplayName ?? info.CFBundleName ?? ''
          appInfo.Version = info.CFBundleShortVersionString
          appInfo.BuildVersion = info.CFBundleVersion
          appInfo.PackageName = info.CFBundleIdentifier
        } else if (appInfo.Platform === 'Android') {
          appInfo.Name = info.application.label.shift() ?? ''
          appInfo.PackageName = info.package
          appInfo.Version = info.versionName
          appInfo.BuildVersion = `${info.versionCode}`
        }
        this.iconBase64 = info.icon
        this.loading = '计算MD5。。。'
        this.iconFile = this.base64ToFile(info.icon, 'icon.png')
        console.log(this.iconFile)
        this.iconMd5 = await this.getFileMd5(this.iconFile)
        appInfo.VersionTitle = `${appInfo.Name}_${appInfo.Version}_${appInfo.BuildVersion}`
        this.fileMd5 = await this.getFileMd5(this.file)
        this.appInfo = appInfo
      } catch (err) {
        console.error(err)
        ElMessage.error(err)
        this.$emit('failed')
      } finally {
        this.loading = null
      }
    },
    getPlatform () {
      // 开始读取文件
      if (!this.file) {
        // 没有文件，返回未知
        return 'unknown'
      }
      if (
        this.file.name.endsWith('.ipa') ||
                this.file.name.endsWith('.IPA')
      ) {
        return 'iOS'
      } else if (
        this.file.name.endsWith('.apk') ||
                this.file.name.endsWith('.APK')
      ) {
        return 'Android'
      } else {
        return 'unknown'
      }
    },
    async submit () {
      try {
        this.loading = '上传中...'
        const filePreKey = `/app/${this.appInfo.PackageName}/${this.appInfo.BuildVersion}`
        this.appInfo.Icon = await this.$uploadFile(this.iconFile, `${filePreKey}/icon-${Date.parse(new Date())}.png`, this.iconMd5, (progress) => {
          this.loading = `${progress}% 上传图标...`
        })
        this.loading = '上传安装包...'
        this.appInfo.DownloadURL = await this.$uploadFile(this.file, `${filePreKey}/app-${Date.parse(new Date())}-${this.file.name}`, this.fileMd5, (progress) => {
          this.loading = `${progress}% 上传安装包...`
        })
        this.loading = '创建APP...'
        await this.$net.post('/app/upload', this.appInfo)
        this.$emit('success')
        ElMessage.success('上传成功！')
      } finally {
        this.loading = null
      }
    },

    cancel () {
      this.$emit('cancel')
    },
    base64ToFile (urlData, fileName) {
      const arr = urlData.split(',')
      const mime = arr[0].match(/:(.*?);/)[1]
      const ia = Base64.toUint8Array(arr[1]) // 解码base64
      return new File([ia], fileName, { type: mime })
    },

    async getFileMd5 (file) {
      if (!file || !(file instanceof File)) {
        return null
      }
      const promis = new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = (e) => {
          const data = CryptoJS.lib.WordArray.create(e.target.result)
          const md5 = CryptoJS.MD5(data).toString()
          resolve(md5)
        }
        reader.onerror = () => {
          reject(reader.error)
        }
        reader.readAsArrayBuffer(file)
      })
      return promis
    }
  },
  mounted () {
    this.loadAppInfo()
  }
}
</script>

<style lang="scss" scoped>
  .app-preview {
    display: block;
    overflow: hidden;
  }
  .app-meta {
    padding: 20px 0;
    text-align: left;
    color: var(--Text);
    border-bottom: solid 1px var(--Border1);
    margin-bottom: 30px;
  }
  .app-meta-property {
    color: var(--SubText);
  }
  .app-icon-col {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100%;
  }
  .platform-icon {
    margin-right: 10px;
    width: 30px;
    border-radius: 15px;
    height: 30px;
  }
  .app-icon {
    width: 80px;
    height: 80px;
    border: 1px solid var(--Border1);
    border-radius: 15px;
    max-width: 100%;
    max-height: 100%;
  }
  .placeholder {
    width: 300px;
    height: 500px;
  }
  .app-loading {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(255, 255, 255, 0.9);
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    color: var(--MainColor);
    div {
      width: 70px;
      height: 70px;
    }
  }
</style>
